package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.acct.facade.request.VirtAcctPreAuthCancelRequest;
import cc.rengu.igas.acct.facade.request.VirtAcctPreAuthCompRequest;
import cc.rengu.igas.acct.facade.response.VirtAcctPreAuthCancelResponse;
import cc.rengu.igas.acct.facade.response.VirtAcctPreAuthCompResponse;
import cc.rengu.igas.acct.facade.result.Result;
import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.BspsTreeNodeConstant;
import cc.rengu.igas.bsps.common.constant.DubboMethodConstant;
import cc.rengu.igas.bsps.common.enums.BspsPayTypeEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.DubboAsynBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.BizStatusEnum;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OrderStatusEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.TxnInfoService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.TxnInfoServiceImpl;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @author: zhangxuran
 * @Date: 2020/3/24 20:10
 * @Description: 余额提现调用ESB超时或异常后续处理
 */
public class AsynMchntCashWithdrawalHandleService extends DubboAsynBaseService {

    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @BIZ_PROCESS
    private void asynMchntCashWithdrawalHandle() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        MchntOrderInfo mchntOrderInfo = (MchntOrderInfo) xmlTreeUtil.getXmlTreeObjectValue(BspsTreeNodeConstant.MCHNT_ORDER_INFO, MchntOrderInfo.class);
        PayOrderInfo payOrderInfo = (PayOrderInfo) xmlTreeUtil.getXmlTreeObjectValue(BspsTreeNodeConstant.PAY_ORDER_INFO, PayOrderInfo.class);
        UserOrderInfo userOrderInfo = (UserOrderInfo) xmlTreeUtil.getXmlTreeObjectValue(BspsTreeNodeConstant.USER_ORDER_INFO, UserOrderInfo.class);
        String payType = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.PAY_TYPE);

        OrderService orderService = new OrderServiceImpl();
        rglog.debug("余额提现调用ESB超时或异常后续处理");
        String respCode = null;
        String respDesc = null;
        boolean success = false;
        if (BspsPayTypeEnum.BANK_CARD_PAY.getPayType().equals(payType)) {
            //TODO 本行卡查证 获取应答内容
//            cc.rengu.igas.channel.esb.facade.result.Result<CoreGeneralTransQueryResponse> esbResult = new cc.rengu.igas.channel.esb.facade.result.Result<>();
//            ConvertUtil.convertOutput(esbResult);
//            success = esbResult.isSuccess();
//            respCode = esbResult.getResult().getRespCode();
//            respDesc = esbResult.getResult().getRespDesc();
        } else {
            //TODO 他行卡查证 获取应答内容
//            cc.rengu.igas.channel.esb.facade.result.Result<IbpsGeneralTransQueryResponse> esbResult = new cc.rengu.igas.channel.esb.facade.result.Result<>();
//            ConvertUtil.convertOutput(esbResult);
//            success = esbResult.isSuccess();
//            respCode = esbResult.getResult().getRespCode();
//            respDesc = esbResult.getResult().getRespDesc();
        }


        //调用查询失败
        if (!success) {
            rglog.error("提现交易状态查询调用失败");
            return;
        }

        if (!BspsAppParamConstant.DUBBO_SUCCESS.equals(respCode)) {
            rglog.error("提现交易状态查询失败，respCode:<{}>,respDesc:<{}>", respCode, respDesc);
            return;
        }

        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
        if (null == mchntInfo) {
            rglog.error("获取商户信息失败,mchntNo:<{}>", mchntOrderInfo.getMchntNo());
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        List<PayOrderInfo> payOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
        if (CollectionUtils.isEmpty(payOrderInfoList)) {
            rglog.error("该支付订单为空, sysSeqNum:<{}>", sysSeqNum);
            return;
        }
        //预授权
        Optional<PayOrderInfo> prePayOrderInfoOptional = payOrderInfoList.stream()
                .filter(item -> ChannelEnum.ACCT.getChannelType().equals(item.getMsgDstId()) && "P06AT100".equals(item.getDstTxnNum())
                        && TransStatusEnum.TRANS_SUCC.getStatus().equals(item.getTransStatus()) && BizStatusEnum.FINISH.getStatus().equals(item.getBizStatus())).findFirst();
        if (!prePayOrderInfoOptional.isPresent()) {
            rglog.error("支付订单表无预授权 dstTxnNum为P06AT100的交易状态为成功且业务状态为处理成功的虚拟账户预授权数据！,sysSeqNum:<{}>,",
                    sysSeqNum);
            return;
        }
        PayOrderInfo preOrderInfo = prePayOrderInfoOptional.get();

        try {
            if (success && BspsAppParamConstant.DUBBO_SUCCESS.equals(respCode)) {
                //更新 ESB提现-支付订单为成功
                userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                boolean dbResult = orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfo);
                if (!dbResult) {
                    rglog.error("更新ESB提现-支付订单状态为成功的数据库操作失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), sysSeqNum);
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                }

                /*  新增支付订单（预授权完成） */
                PayOrderInfo acctAuthCompPayOrderInfo = initAcctPayOrderInfo(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getSysSeqNum(),
                        mchntOrderInfo.getMchntSettleAmt(), "3");
                dbResult = orderService.registerOrderInfo(null, null, acctAuthCompPayOrderInfo);
                if (!dbResult) {
                    rglog.error("提现交易成功，新增预授权完成支付订单信息失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
                    throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
                }

                /*  TODO 调用虚拟账户进行预授权完成 */
                VirtAcctPreAuthCompRequest virtAcctPreAuthCompRequest = new VirtAcctPreAuthCompRequest();
                cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
                header.setInstId(userOrderInfo.getInstId());
                header.setTxnNum(acctAuthCompPayOrderInfo.getDstTxnNum());
                header.setTraceNo(acctAuthCompPayOrderInfo.getChannelSeqNum());
                header.setSrcSysId(AppParamConstant.SYS_ID);
                header.setChanlId(BspsAppParamConstant.BSP_SYS_ID);
                header.setTransTime(DateUtil.getCurrentTime());
                header.setTransDate(DateUtil.getCurrentDate());
                virtAcctPreAuthCompRequest.setHeader(header);
                virtAcctPreAuthCompRequest.setAcctType("00");
                //userType : 00-商户  01-会员 02-营销
                virtAcctPreAuthCompRequest.setUserType("00");
                virtAcctPreAuthCompRequest.setTransAmt(acctAuthCompPayOrderInfo.getRealPayAmt());
                virtAcctPreAuthCompRequest.setUserId(mchntOrderInfo.getMchntNo());
                virtAcctPreAuthCompRequest.setFreezeAcctSeqNum(preOrderInfo.getChannelOrderId());
                if (BspsAppParamConstant.FLAG_N.equals(mchntInfo.getIndependentDataFlag())) {
                    //非独立维护，填连锁商户号
                    virtAcctPreAuthCompRequest.setUserId(mchntInfo.getChainMchntNo());
                }
                DubboService dubboService = new DubboServiceImpl();
                Result<VirtAcctPreAuthCompResponse> acctDubboResult = (Result<VirtAcctPreAuthCompResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_VIRT_ACCT_SERVICE, "virtAcctPreAuthComp", virtAcctPreAuthCompRequest);
                VirtAcctPreAuthCompResponse virtAcctPreAuthCompResponse = acctDubboResult.getResult();
                if (acctDubboResult.isSuccess() && "00".equals(virtAcctPreAuthCompResponse.getTransStatus())) {
                    //更新 虚拟账户预授权完成-支付订单为成功
                    acctAuthCompPayOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                    acctAuthCompPayOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    acctAuthCompPayOrderInfo.setRespCode(virtAcctPreAuthCompResponse.getRespCode());
                    acctAuthCompPayOrderInfo.setRespDesc(virtAcctPreAuthCompResponse.getRespDesc());
                    dbResult = orderService.updateOrderInfo(null, null, acctAuthCompPayOrderInfo);
                    if (!dbResult) {
                        rglog.error("交易提现 更新虚拟账户预授权完成支付订单的数据库操作失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
                        throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                    }
                } else {
                    //更新 虚拟账户预授权完成-支付订单为失败
                    acctAuthCompPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    acctAuthCompPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    acctAuthCompPayOrderInfo.setRespCode(virtAcctPreAuthCompResponse.getRespCode());
                    acctAuthCompPayOrderInfo.setRespDesc(virtAcctPreAuthCompResponse.getRespDesc());
                    dbResult = orderService.updateOrderInfo(null, null, acctAuthCompPayOrderInfo);
                    if (!dbResult) {
                        rglog.error("交易提现 更新虚拟账户预授权完成-支付订单状态为失败的数据库操作失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
                        throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                    }
                }
            } else if (BspsAppParamConstant.DUBBO_OVERTIME.equals(respCode)) {
                rglog.error("异步进行提现交易状态查询，查询超时。");
            } else {
                //更新 ESB提现-支付订单为失败， 进行预授权撤销
                userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                boolean dbResult = orderService.updateOrderInfo(userOrderInfo, Arrays.asList(mchntOrderInfo), payOrderInfo);
                if (!dbResult) {
                    rglog.error("交易提现 更新ESB提现-支付订单状态为成功的数据库操作失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), sysSeqNum);
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                }

                /*  新增支付订单（预授权撤销） */
                PayOrderInfo acctAuthCancelPayOrderInfo = initAcctPayOrderInfo(mchntOrderInfo.getOrderAmt(), mchntOrderInfo.getSysSeqNum(),
                        mchntOrderInfo.getMchntSettleAmt(), "4");
                dbResult = orderService.registerOrderInfo(null, null, acctAuthCancelPayOrderInfo);
                if (!dbResult) {
                    rglog.error("交易提现- 预授权撤销支付订单失败，提现交易失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
                    throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
                }

                /* TODO 调用虚拟账户进行预授权撤销 */
                VirtAcctPreAuthCancelRequest virtAcctPreAuthCancelRequest = new VirtAcctPreAuthCancelRequest();
                cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
                header.setInstId(userOrderInfo.getInstId());
                header.setTxnNum(acctAuthCancelPayOrderInfo.getDstTxnNum());
                header.setTraceNo(acctAuthCancelPayOrderInfo.getChannelSeqNum());
                header.setSrcSysId(AppParamConstant.SYS_ID);
                header.setChanlId(BspsAppParamConstant.BSP_SYS_ID);
                header.setTransTime(DateUtil.getCurrentTime());
                header.setTransDate(DateUtil.getCurrentDate());
                virtAcctPreAuthCancelRequest.setHeader(header);
                virtAcctPreAuthCancelRequest.setAcctType("00");
                //userType : 00-商户  01-会员 02-营销
                virtAcctPreAuthCancelRequest.setUserType("00");
                virtAcctPreAuthCancelRequest.setTransAmt(acctAuthCancelPayOrderInfo.getRealPayAmt());
                virtAcctPreAuthCancelRequest.setUserId(mchntOrderInfo.getMchntNo());
                virtAcctPreAuthCancelRequest.setFreezeAcctSeqNum(preOrderInfo.getChannelOrderId());
                if (BspsAppParamConstant.FLAG_N.equals(mchntInfo.getIndependentDataFlag())) {
                    //非独立维护，填连锁商户号
                    virtAcctPreAuthCancelRequest.setUserId(mchntInfo.getChainMchntNo());
                }

                DubboService dubboService = new DubboServiceImpl();
                Result<VirtAcctPreAuthCancelResponse> acctDubboResult = (Result<VirtAcctPreAuthCancelResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_VIRT_ACCT_SERVICE, "virtAcctPreAuthCancel", virtAcctPreAuthCancelRequest);
                VirtAcctPreAuthCancelResponse cancelResponse = acctDubboResult.getResult();
                if (acctDubboResult.isSuccess() && "00".equals(cancelResponse.getTransStatus())) {
                    //更新 虚拟账户预授权撤销-支付订单为成功
                    acctAuthCancelPayOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                    acctAuthCancelPayOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                    acctAuthCancelPayOrderInfo.setRespCode(cancelResponse.getRespCode());
                    acctAuthCancelPayOrderInfo.setRespDesc(cancelResponse.getRespDesc());
                    dbResult = orderService.updateOrderInfo(null, null, acctAuthCancelPayOrderInfo);
                    if (!dbResult) {
                        rglog.error("更新虚拟账户预授权撤销-支付订单状态为成功的数据库操作失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
                        throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                    }
                } else {
                    //更新 虚拟账户预授权撤销-支付订单为失败
                    acctAuthCancelPayOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    acctAuthCancelPayOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    acctAuthCancelPayOrderInfo.setRespCode(cancelResponse.getRespCode());
                    acctAuthCancelPayOrderInfo.setRespDesc(cancelResponse.getRespDesc());
                    dbResult = orderService.updateOrderInfo(null, null, acctAuthCancelPayOrderInfo);
                    if (!dbResult) {
                        rglog.error("更新虚拟账户预授权撤销-支付订单状态为失败的数据库操作失败！instId:<{}>，sysSeqNum：<{}>", mchntOrderInfo.getInstId(), mchntOrderInfo.getSysSeqNum());
                        throw new BizException(RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
                    }
                }
            }

        } catch (Exception e) {
            rglog.error("余额提现调用ESB超时或异常后续处理失败 sysSeqNum:<{}>. ", sysSeqNum);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
            rglog.error("余额提现调用ESB超时或异常后续处理异步流程异常信息:<{}>", byteArrayOutputStream.toString());
        }
    }

    private PayOrderInfo initAcctPayOrderInfo(String orderAmt, String sysSeqNum, String realPayAmt, String dstCallIndex) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        TxnInfo txnInfo = (TxnInfo) xmlTreeUtil.getXmlTreeObjectValue(TreeNodeConstant.TXN_INFO, TxnInfo.class);
        Optional<ChannelCallCfg> channelCallCfgOptional = txnInfo.getChannelCallCfgList().stream()
                .filter(item -> ChannelEnum.ACCT.getChannelType().equals(item.getCallChannelId()) && dstCallIndex.equals(item.getCallIndex())).findFirst();
        if (!channelCallCfgOptional.isPresent()) {
            rglog.error("通道服务调用配置表无序号为{}的数据！,sysSeqNum:<{}>,",
                    dstCallIndex, sysSeqNum);
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        //获取通道服务调用配置
        ChannelCallCfg channelCallCfg = channelCallCfgOptional.get();

        PayOrderInfo payOrderInfo = new PayOrderInfo();
        ConvertUtil.convertOutput(payOrderInfo);
        payOrderInfo.setSysSeqNum(sysSeqNum);
        payOrderInfo.setMchntOrderId(sysSeqNum);
        payOrderInfo.setOrderAmt(orderAmt);
        payOrderInfo.setRealPayAmt(realPayAmt);
//        payOrderInfo.setOrigSysSeqNum(oriPayOrderInfo.getChannelOrderId());
        //交易通道标识
        payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
        //支付通道流水号
        String channelSeqNum = sysSeqNum + dstCallIndex;
        payOrderInfo.setChannelSeqNum(channelSeqNum);
        //支付通道对账唯一KEY  虚拟账户：系统流水号+调用序号
        payOrderInfo.setChannelReconKey(channelSeqNum);
        //通道调用序号
        payOrderInfo.setDstCallIndex(dstCallIndex);
        //通道交易码
        payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setPayType("*");
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return payOrderInfo;
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }
}
